/**
 * @fileoverview
 * Custom rendering logic for the image mashup application
 */
 

/** 
 * Create a new custom genefinder renderer instance.
 * @class
 * A custom renderer for the GeneFinder Widget.
 * @constructor
 * @param {Element} renderPane the element to which the widget is rendered
 */
CustomGeneFinderRenderer = function( renderPane ) {

	
	var that = this;
	
	/**
	 * @private
	 */
	this._query = null;
	
	/**
	 * @private
	 */
	this._results = null;
	
	/**
	 * @private
	 */
	this._containerPane = renderPane;
	
	
	/**
	 * @private
	 */
	this._pendingPane = null;


	/**
	 * @private
	 */
	this._messagePane = null;
	 
	
	/**
	 * @private
	 */
	this._resultsSummaryPane = null;
	

	/**
	 * @private
	 */
	this._resultsPane = null;
	
	
	/**
	 * @private
	 */
	this._onResultClicked = null;


	/**
	 * TODO doc me
	 */
	this.setResultClickHandler = function( handler ) {
		this._onResultClicked = handler;
	}

	/**
	 * TODO doc me
	 * @private
	 */
	this._onStateChanged = function( oldVal, newVal ) {
		
		if ( newVal == "PENDING" ) {
			flyui.mvcutils.show(that._pendingPane);
			flyui.mvcutils.hide(that._messagePane);
			flyui.mvcutils.hide(that._resultsSummaryPane);
			flyui.mvcutils.hide(that._resultsPane);
		}
		else if ( newVal == "READY" ) {
			flyui.mvcutils.hide(that._pendingPane);
			flyui.mvcutils.show(that._messagePane);
			flyui.mvcutils.show(that._resultsSummaryPane);
			flyui.mvcutils.show(that._resultsPane);			
		} 
		else if ( newVal == "SERVERERROR" || newVal == "UNEXPECTEDERROR" ) {
			flyui.mvcutils.hide(that._pendingPane);
			flyui.mvcutils.show(that._messagePane);
			flyui.mvcutils.hide(that._resultsSummaryPane);
			flyui.mvcutils.hide(that._resultsPane);			
		} 
		else {
			// this should never happen
			throw {name:"flyui.genefinder.UnexpectedStateError", message:"Invalid state: "+newVal};
		}
		
		
	};


	/**
	 * TODO doc me
	 * @private
	 */
	this._onQueryChanged = function( oldVal, newVal ) {
		// temporarily store the query
		that._query = newVal;
	};


	/**
	 * TODO doc me
	 * @private
	 */
	this._onResultsChanged = function( oldVal, genes ) {

		// temporarily store the results
		that._results = genes;
		
		// set the results summary
		that._renderResultsSummary(that._query, genes.length);
		
		if (genes.length > 0) {
			
			// empty the results pane
			that._resultsPane.innerHTML = "";	

			// set the content
			var table = that.genesToTableNode(genes);
			log("table content:"+table.innerHTML, "debug");
			that._resultsPane.appendChild(table);	
			
			// set the message pane content
			that._messagePane.innerHTML = "selected gene: <strong>please select one of the genes from the list above, or try another query</strong>";

		}
		else {
			that._resultsPane.innerHTML = "";
			that._messagePane.innerHTML = "";
		}
	};
	

	/**
	 * TODO doc me
	 * @private
	 */
	this._onSelectionIndexChanged = function( oldIndex, newIndex ) {
		log("onSelectionIndexChanged, old:"+oldIndex+", new:"+newIndex, "debug");
		
//		// get the table
//		var table = that._resultsPane.childNodes[0];
//		
//		log("results table: "+table.innerHTML, "debug");
		
		// get the rows
		var rows = that._resultsPane.getElementsByTagName("tr");
		
		if (oldIndex != null) {
			// remove class
			YAHOO.util.Dom.removeClass(rows[oldIndex+1], "selected");
		}
		
		if (newIndex != null) {
			// add class
//			log("adding selected class to row: "+rows[newIndex+1], "debug");
			YAHOO.util.Dom.addClass(rows[newIndex+1], "selected");
			var gene = that._results[newIndex];
			that._messagePane.innerHTML = "selected gene: <strong>"+gene.symbols.join(" / ")+"</strong> [<a href='http://flybase.org/reports/"+gene.flybaseID+".html'>FlyBase Gene Report</a>]";
		}
	};
	
	
	/**
	 * TODO doc me
	 * @private
	*/
	this._onErrorMessageChanged = function( oldVal, newVal ) {
		that._messagePane.innerHTML = newVal;
	};
	
	
	/**
	 * TODO doc me
	 * @private
	 */
	this._init = function() {
		
		// setup pending pane
		this._pendingPane = document.createElement("p");
		this._pendingPane.innerHTML = "pending...";
		this._containerPane.appendChild(this._pendingPane);
		flyui.mvcutils.hide(this._pendingPane);

		// setup results summary pane
		this._resultsSummaryPane = document.createElement("p");
		this._resultsSummaryPane.innerHTML = "this should never be displayed";
		this._containerPane.appendChild(this._resultsSummaryPane);
		flyui.mvcutils.hide(this._resultsSummaryPane);
		
		// setup results pane
		this._resultsPane = document.createElement("div");
		this._containerPane.appendChild(this._resultsPane);
		flyui.mvcutils.hide(this._resultsPane);

		// message pane
		this._messagePane = document.createElement("p");
		this._messagePane.innerHTML = "this should never be displayed";
		this._containerPane.appendChild(this._messagePane);
		flyui.mvcutils.hide(this._messagePane);
					
	};
	
	
	// do initialisation
	this._init();
	
	
}


/**
 * TODO doc me
 */
CustomGeneFinderRenderer.prototype.connect = function( model ) {
		
	model.addListener("STATE", this._onStateChanged);
	model.addListener("QUERY", this._onQueryChanged);
	model.addListener("RESULTS", this._onResultsChanged);
	model.addListener("ERRORMESSAGE", this._onErrorMessageChanged);
	model.addListener("SELECTIONINDEX", this._onSelectionIndexChanged);

}


CustomGeneFinderRenderer.prototype._renderResultsSummary = function( query, count ) {
	var content = "found ";
	content += count;
	content += " matching gene";
	content += (count == 0 || count > 1) ? "s " : " ";
	content += "from <a href='http://www.flybase.org'>www.flybase.org</a> for query '"+query+"'";
	this._resultsSummaryPane.innerHTML = content;
}

/**
 * Helper function for building DOM elements containing lists of elements
 * @param {string} outerTag outer tag (e.g. "TR") 
 * @param {string} innerTag inner tag (e.g. "TD") 
 * @param {string*} list of inner HTML values to populate element
 * @return a new DOM element constructed from supplied values
 * @type HTMLElement 
 */
CustomGeneFinderRenderer.renderDomElementFromList = function(outerTag, innerTag, list) {

	var outerElem = document.createElement(outerTag);

	// can we defer this to caller?  tbody.appendChild(headerRow);
	
	log("creating outer "+outerTag, "debug");
	for (var i=0; i<list.length; i++) {
		var innerElem = document.createElement(innerTag);
		innerElem.innerHTML = list[i];
		outerElem.appendChild(innerElem);
	}	

	return outerElem;	
}


/**
 * TODO doc me
 */
CustomGeneFinderRenderer.prototype.genesToTableNode = function( genes ) {
	
	// set up overall table structure
	var table = document.createElement("table");
	var thead = document.createElement("thead");
	var tbody = document.createElement("tbody");
	table.appendChild(thead);
	table.appendChild(tbody);

	// set up header row
	var headers = ["symbol", "full name", "annotation ID", "flybase ID", "user selection"];
	var headerRow = CustomGeneFinderRenderer.renderDomElementFromList("tr", "th", headers); 
	thead.appendChild(headerRow);
	
	for (var i=0; i<genes.length; i++) {
		log("creating result row "+i, "debug");
		var cellContents = CustomGeneFinderRenderer.geneToTableCellContents(genes[i]);
		var row = CustomGeneFinderRenderer.renderDomElementFromList("tr", "td", cellContents);
		tbody.appendChild(row);
		YAHOO.util.Event.addListener(row, "click", this._onResultClicked, i);
	}
	
	return table;
}


CustomGeneFinderRenderer.geneToTableCellContents = function( gene ) {
	return [
		gene.symbols.join(" / "),
		gene.fullNames.join(" / "),
		gene.annotationSymbols.join(" / "),
		gene.flybaseID,
		"<span class='selector'>[<a href='javascript:void(0)'>select this gene</a>]</span><span class='isselected'>selected</span>"
	];
}



/* *******************************************************
 * custom flyted rendering
 * *******************************************************
 */

/**
 * TODO doc me
 * @class
 * @constructor
 */
CustomFlytedRenderer = function( renderPane ) {
	
	var that = this;
	
	/** @private */
	this._containerPane = renderPane;
	
	/**
	 * @private
	 */
	this._onStateChanged = function( oldState, newState ) {
		if ( newState == "PENDING" ) {
			flyui.mvcutils.show(that._pendingPane);
			flyui.mvcutils.hide(that._messagePane);
			flyui.mvcutils.hide(that._resultsSummaryPane);
			flyui.mvcutils.hide(that._resultsPane);
		} 
		else if (newState == "READY") {
			flyui.mvcutils.hide(that._pendingPane);
			flyui.mvcutils.hide(that._messagePane);
			flyui.mvcutils.show(that._resultsSummaryPane);
			flyui.mvcutils.show(that._resultsPane);		
		}
		else if ( newState == "SERVERERROR" || newState == "UNEXPECTEDERROR" ) {
			flyui.mvcutils.hide(that._pendingPane);
			flyui.mvcutils.show(that._messagePane);
			flyui.mvcutils.hide(that._resultsSummaryPane);
			flyui.mvcutils.hide(that._resultsPane);			
		} 
		else {
			// this should never happen
			throw {name:"flyui.flyted.ImageWidget.UnexpectedStateError", message:"Invalid state: "+newState};
		}
	};

	/**
	 * @private
	 */
	this._onQueryChanged = function( oldQuery, newQuery ) {
		// store query
		that._query = newQuery;
	};
	
	
	/**
	 * @private
	 */
	this._onResultsChanged = function( oldResults, newResults ) {
		// render the results summary
		that._renderResultsSummary(that._query, newResults.length);
		
		if (newResults.length > 0) {
			
			// set the content
			that._resultsPane.innerHTML = CustomFlytedRenderer.imagesToDivHTML(newResults);	

		}
		else {
			that._resultsPane.innerHTML = "";
		}
	};
	
	
	/**
	 * @private
	 */
	this._onErrorMessageChanged = function( oldMsg, newMsg) {
		that._messagePane.innerHTML = newMsg;
	};
	
	
	/**
	 * @private
	 */
	this._init = function() {
		
		// set up the pending pane
		this._pendingPane = document.createElement("div");
		this._pendingPane.innerHTML = "<p>Pending...</p>";
		this._containerPane.appendChild(this._pendingPane);
		flyui.mvcutils.hide(this._pendingPane);
		
		// set up the message pane
		this._messagePane = document.createElement("div");
		this._messagePane.innerHTML = "this should never be displayed";
		this._containerPane.appendChild(this._messagePane);
		flyui.mvcutils.hide(this._messagePane);
		
		// setup results summary pane
		this._resultsSummaryPane = document.createElement("p");
		this._containerPane.appendChild(this._resultsSummaryPane);
		flyui.mvcutils.hide(this._resultsSummaryPane);
		
		// setup results pane
		this._resultsPane = document.createElement("div");
		this._containerPane.appendChild(this._resultsPane);
		flyui.mvcutils.hide(this._resultsPane);

	};
	
	// do initialisation
	this._init();
	
};


/**
 * TODO doc me
 */
CustomFlytedRenderer.prototype.connect = function( model ) {
	model.addListener("STATE", this._onStateChanged);
	model.addListener("QUERY", this._onQueryChanged);
	model.addListener("RESULTS", this._onResultsChanged);
	model.addListener("ERRORMESSAGE", this._onErrorMessageChanged);
};


CustomFlytedRenderer.prototype._renderResultsSummary = function( query, count ) {
	var content = "found ";
	content += count;
	content += " matching image";
	content += (count == 0 || count > 1) ? "s " : " ";
	content += "from <a href='http://www.fly-ted.org'>www.fly-ted.org</a> for ";
	if (query instanceof flyui.flybase.Gene) {
		content += "gene <strong>"+query.symbols.join(" / ")+"</strong>";
		var ftnames = flyui.flyted.GeneNameMappings.flybaseToFlyted[query.flybaseID];
		if (typeof ftnames == "undefined" || !ftnames) {
			content += " (no mapping found to FlyTED gene names";
		}
		else if (ftnames.length == 1) {
			content += " (mapped to FlyTED gene name <strong><a href='http://www.fly-ted.org/view/geneid/"+ftnames[0]+".html'>"+ftnames[0]+"</a></strong>";			
		}
		else if (ftnames.length > 1) {
			content += "(mapped to FlyTED gene names ";
			for (var i=0; i<ftnames.length; i++) {
				content += "<strong><a href='http://www.fly-ted.org/view/geneid/"+ftnames[i]+".html'>"+ftnames[i]+"</a></strong>";
				if (i < ftnames.length) content += ", ";
			}
		}		
		content += ", N.B. gene name mappings may contain errors, check source data carefully)";
	} else {
		content += 	"query '"+query+"'";
	}
	this._resultsSummaryPane.innerHTML = content;
}


/**
 * TODO doc me
 */
CustomFlytedRenderer.imagesToDivHTML = function( images ) {
	
	// build the divs
	
	var content = "";
	for ( var i in images ) {
		
		content += CustomFlytedRenderer.imageToDivHTML(images[i]);
		log ("Generate the img div" + content, "test");	
	}
	
	return content;
};


/**
 * TODO doc me
 */
CustomFlytedRenderer.imageToDivHTML = function( image ) {
 	
 	//TODO include the caption
 	
 	var content = 	"<div class=\"result\">";
	content +=			"<p><a href=\"" + image.flytedURL + "\">";
	content +=				"<img src=\"" + image.thumbnailURL + "\" alt=\"this is an image\">";
	content +=			"</img></a></p>"; 
	content +=			"<p>"+image.caption+"</p>"
	content +=		"</div>";
	
	return content;
};


/* *******************************************************
 * custom bdgp rendering
 * *******************************************************
 */
 
 
 
/**
 * TODO doc me
 * @class
 * @constructor
 */
CustomBdgpRenderer = function( renderPane ) {
	var that = this;
	
	/** @private */
	this._containerPane = renderPane;
	
	this._onStateChanged = function (oldState, newState) {
		if ( newState == "PENDING" ) {
			flyui.mvcutils.show(that._pendingPane);
			flyui.mvcutils.hide(that._messagePane);
			flyui.mvcutils.hide(that._resultsSummaryPane);
			flyui.mvcutils.hide(that._resultsPane);
		} 
		else if (newState == "READY") {
			flyui.mvcutils.hide(that._pendingPane);
			flyui.mvcutils.hide(that._messagePane);
			flyui.mvcutils.show(that._resultsSummaryPane);
			flyui.mvcutils.show(that._resultsPane);		
		}
		else if ( newState == "SERVERERROR" || newState == "UNEXPECTEDERROR" ) {
			flyui.mvcutils.hide(that._pendingPane);
			flyui.mvcutils.show(that._messagePane);
			flyui.mvcutils.hide(that._resultsSummaryPane);
			flyui.mvcutils.hide(that._resultsPane);			
		} 
		else {
			// this should never happen
			throw {name:"flyui.bdgp.ImageWidget.UnexpectedStateError", message:"Invalid state: "+newState};
		}
	};
	
	this._onErrorMessageChanged = function (oldErr, newErr){
		that._messagePane.innerHTML = newErr;
	};
	
	this._onResultsChanged = function(oldResults, newResults) {
		// render the results summary
		that._renderResultsSummary(that._query, newResults.length);
		
		if (newResults.length > 0) {
			
			// set the content
			that._resultsPane.innerHTML = CustomBdgpRenderer.imagesToDivHTML(newResults);
			
		}
		else {
			that._resultsPane.innerHTML = "";
		}
	};
	
	this._onQueryChanged = function (oldQuery, newQuery){
		// store the query
		that._query = newQuery;
	}
	
	/**
	 * @private
	 */
	this._init = function() {
		
		// set up the pending pane
		this._pendingPane = document.createElement("p");
		this._pendingPane.innerHTML = "pending...";
		this._containerPane.appendChild(this._pendingPane);
		flyui.mvcutils.hide(this._pendingPane);
		
		// set up the message pane
		this._messagePane = document.createElement("p");
		this._messagePane.innerHTML = "this should never be displayed";
		this._containerPane.appendChild(this._messagePane);
		flyui.mvcutils.hide(this._messagePane);
		
		// setup results summary pane
		this._resultsSummaryPane = document.createElement("p");
		this._containerPane.appendChild(this._resultsSummaryPane);
		flyui.mvcutils.hide(this._resultsSummaryPane);
		
		// set up results summary content
		this._resultsSummaryCountPane = document.createElement("span");
		this._resultsSummaryCountPane.innerHTML = "this should never be displayed";
		this._resultsSummaryQueryPane = document.createElement("span");
		this._resultsSummaryQueryPane.innerHTML = "this should never be displayed";
		this._resultsSummaryPane.appendChild(document.createTextNode("found "));
		this._resultsSummaryPane.appendChild(this._resultsSummaryCountPane);
		this._resultsSummaryPane.appendChild(document.createTextNode(" images for gene \""));
		this._resultsSummaryPane.appendChild(this._resultsSummaryQueryPane);
		this._resultsSummaryPane.appendChild(document.createTextNode("\""));
		
		// setup results pane
		this._resultsPane = document.createElement("div");
		this._containerPane.appendChild(this._resultsPane);
		flyui.mvcutils.hide(this._resultsPane);

	};
	
	// do initialisation
	this._init();
	
}

/**
 * connect listeners for any changes to the Model
 * TODO doc me
 */
CustomBdgpRenderer.prototype.connect = function( model ) {
	
	model.addListener("STATE", this._onStateChanged);
	model.addListener("QUERY", this._onQueryChanged);
	model.addListener("RESULTS", this._onResultsChanged);
	model.addListener("ERRORMESSAGE", this._onErrorMessageChanged);
};

CustomBdgpRenderer.prototype._renderResultsSummary = function( query, count ) {
	var content = "found ";
	content += count;
	content += " matching image";
	content += (count == 0 || count > 1) ? "s " : " ";
	content += "from <a href='http://www.fruitfly.org'>www.fruitfly.org</a> for ";
	if (query instanceof flyui.flybase.Gene) {
		content += "gene <strong>"+query.symbols.join(" / ")+"</strong> [<a href='http://www.fruitfly.org/cgi-bin/ex/bquery.pl?qtype=report&find="+query.annotationSymbols[0]+"&searchfield=CG'>BDGP gene report</a>]";
	} else {
		content += 	"query '"+query+"'";
	}
	this._resultsSummaryPane.innerHTML = content;
}


/**
 * TODO doc me
 */
CustomBdgpRenderer.imagesToDivHTML = function( images ) {
	
	// build the divs
	
	var content = "";
	for ( var i in images ) {
		
		content += CustomBdgpRenderer.imageToDivHTML(images[i]);
		log ("Generate the img div" + content, "test");	
	}
	
	return content;
};


/**
 * TODO doc me
 */
CustomBdgpRenderer.imageToDivHTML = function( image ) {
 	
 	//TODO include the caption
 	
 	var content = 	"<div class=\"result\">";
	content +=			"<a href=\"" + image.fullImageURL + "\">";
	content +=				"<img src=\"" + image.thumbnailURL + "\" alt=\"this is an image\">";
	content +=			"</img></a>"; 
	content +=		"</div>";
	
	return content;
};
 
